﻿using System.IO;
using System.Net;
using System.Net.Sockets;

namespace sinetd.Protocols.Tcp
{
    public class Protocol : BaseProtocol, IProtocol
    {
        TcpListener listener;

        TcpClient client;
        NetworkStream stream;
        StreamReader reader;
        StreamWriter writer;

        public override void ConfigDefault()
        {
            cfg.SetDefault("port", "0");
            cfg.SetDefault("host", "127.0.0.1");
            cfg.SetDefault("readtoend", "false");
        }
        
        public Protocol() : base("Tcp") { }

        public Protocol(TcpClient client, string id) : base("Tcp", id)
        {
            stream = client.GetStream();
            reader = new StreamReader(stream);
            writer = new StreamWriter(stream);
            writer.AutoFlush = true;
        }

        #region IProtocol Members

        public void Bind(AcceptClientHandler AcceptClient)
        {
            listener = new TcpListener(Dns.GetHostAddresses(cfg.GetString("host"))[0], cfg.GetInt32("port"));
            StartThread(() =>
            {
                try
                {
                    listener.Start();
                }
                catch { TerminatePending = true; }

                while (!TerminatePending)
                {
                    client = null;
                    try
                    {
                        client = listener.AcceptTcpClient();
                    }
                    catch { }
                    if (client != null)
                    {
                        AcceptClient(new Protocol(client, Id));
                    }
                }
            });
        }

        public bool Connect()
        {
            try
            {
                client = new TcpClient(cfg.GetString("host"), cfg.GetInt32("port"));
                stream = client.GetStream();

                reader = new StreamReader(stream);
                writer = new StreamWriter(stream);
                writer.AutoFlush = true;
                return true;
            }
            catch
            {
                return false;
            }
        }

        public void Send(string msg)
        {
            writer.WriteLine(msg);
        }

        public string Recv()
        {
            string msg = reader.ReadLine();
            if (cfg.GetBoolean("readtoend"))
                msg += reader.ReadToEnd();
            return msg;
        }

        public void Close()
        {
            if (listener != null) listener.Stop();
            StopThread();

            if (writer != null) writer.Close();
            if (reader != null) reader.Close();
            if (stream != null) stream.Close();
            if (client != null) client.Close();
        }

        #endregion
    }
}
